package studystat;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.lang.Long;

/**
 * Statistiek beheert alle statistieken en hierbij dus ook de informatie van studenten
 * @author CWB4
 */
public class Statistiek {
	 
	//Lijst die alle mogelijke studieplaatsen bevat
	List<String> studiePlaatsLijst; 
	//Om er een singleton van te maken
	private static Statistiek instance = null;
	
	/**
	 * Maak een nieuw statistiek object
	 */
	public Statistiek() {
		addStudiePlaatsen();
	}
	
	/**
	 * @return Een instance van de statistiek-singleton
	 */
	public static Statistiek getInstance() {
		if (instance == null) {
			instance = new Statistiek();
		}
		return instance;
	}
	
	/**
	 * Synchroniseer de achievements van de student
	 * @param student	De student wiens achievements worden gesynchroniseerd
	 */
	public void syncAchievements(Student student) {
		List<Achievement> behaaldeAchievements = AchievementManager.getInstance().sync(student.getActiviteiten());
		student.addAchievements(behaaldeAchievements);
	}
	
	/**
	 * Synchroniseer alle studenten hun achievements
	 */
	public void syncAchievements() {
		for(Student student: StudentManager.getInstance().getStudents()) {
			syncAchievements(student);
		}
	}
	
	
	/**
	 * Deze methode berekent hoeveel tijd de student in het totaal reeds heeft besteed aan studeren
	 * @param student	De student wiens studietijd wordt berekend
	 * @return de totale gespendeerde studietijd van de student in minuten
	 */
	public int berekenTotaleStudietijd(Student student) {
		List<Studie> studies = student.getStudies();
		int i=0;
		int totaleDuur=0;
		// Overloop alle studie-activiteiten van de student en tel dit op bij totaleDuur
		while (i < studies.size()) {
			Long huidigeDuur = studies.get(i).getDuur();
			totaleDuur = totaleDuur + huidigeDuur.intValue(); 
			i++;
		}
		return totaleDuur;
	}
	
	/**
	 * Deze methode berekent de totale studietijd van alle studenten tesamen
	 * @return totale studietijd van alle studenten tesamen in minuten
	 */
	public int berekenTotaleStudietijdAlleStudenten() {
		List<Student> studenten = StudentManager.getInstance().getStudents();
		int totaleDuurAlleStudenten = 0;
		int j=0;
		while (j < studenten.size()) {
			Student huidigeStudent = studenten.get(j);
			int totaleDuur = berekenTotaleStudietijd(huidigeStudent);
			totaleDuurAlleStudenten = totaleDuurAlleStudenten + totaleDuur;
			j++;
		}
		return totaleDuurAlleStudenten;
	 }
	
	/**
	 * Deze methode haalt alle studieactiviteiten van een student op, berekent 
	 * de totale gespendeerde tijd per vak en slaat dit op in een HashMap
	 * @param student	De student wiens studietijden per vak worden berekend
	 * @return een HashMap die alle vakken en bijhorende gespendeerde tijden bevat
	 */
	
	public HashMap<Vak,Integer> berekenDuurVakken(Student student) {
		
		HashMap<Vak,Integer> vakkenMap = new HashMap<Vak,Integer>();
		
		String type = "studietijd";
		vakkenMap = berekenAantal(student, type);
		
		return vakkenMap;
	}
	
	
	/**
	 * Deze methode retourneert een HashMap die alle vakken van een bepaalde 
	 * student als keys bevat en de bijbehorende percentages die een student 
	 * aan per vak gespendeerd heeft als values
	 * @param student	De student wiens percentages worden berekend
	 * @return HashMap met studietijd in percentages per vak 
	 */
	
	public HashMap<Vak,Integer> berekenPercentagesVakken(Student student) {
		
		int duurAlleVakken = berekenTotaleStudietijd(student);
		
		HashMap<Vak,Integer> vakkenMap = new HashMap<Vak,Integer>();
		vakkenMap = berekenDuurVakken(student);
		
		List<Vak> vakkenLijst = new ArrayList<Vak>();
		vakkenLijst = student.getVakken();
		
		if(duurAlleVakken != 0) {
			int i = 0;
			while(i<vakkenLijst.size()) {
				int duur = vakkenMap.get(vakkenLijst.get(i));
				int percentage = (100*duur)/duurAlleVakken;
				vakkenMap.remove(vakkenLijst.get(i));
				vakkenMap.put(vakkenLijst.get(i), percentage);
				i++;
			}
		}
		
		return vakkenMap;
	}
	
	/**
	 * Dze methode retourneert de gemiddelde percentages van alle studenten die 
	 * ze gespendeerd hebben aan de verschillende vakken 
	 *@return HashMap met vakken en bijhorende percentages
	 */
	
	public HashMap<Vak,Integer> berekenGemiddeldePercentagesVakken(Student currentStudent) {
		
		HashMap<Vak,Integer> gemiddeldeVakkenMap = new HashMap<Vak,Integer>();
		HashMap<Vak,Integer> gemiddeldeVakkenMap2 = new HashMap<Vak,Integer>();
		
		//Bevat verschillende vakken als keys en het aantal gemiddeldes van
		//alle studenten per vak als values
		HashMap<Vak,Integer> aantalGemiddeldes = new HashMap<Vak,Integer>();
		
		List<Vak> vakkenLijst = new ArrayList<Vak>();
		vakkenLijst = VakManager.getInstance().getVakken();
		
		List<Student> studenten = StudentManager.getInstance().getStudents();
		
		
		//Initialisatie van de HashMaps, zet de vakken erin als keys met waarde nul
		int k=0;
		while(k<vakkenLijst.size()) {
			gemiddeldeVakkenMap.put(vakkenLijst.get(k), 0);
			gemiddeldeVakkenMap2.put(vakkenLijst.get(k), 0);
			aantalGemiddeldes.put(vakkenLijst.get(k), 0);
			k++;
		}
		
		int i = 0;
		while(i<studenten.size()) {
			HashMap<Vak,Integer> vakkenMap = new HashMap<Vak,Integer>();
			vakkenMap = berekenPercentagesVakken(studenten.get(i));
			int j = 0;
			while(j<vakkenLijst.size()) {
				if(vakkenMap.get(vakkenLijst.get(j)) != null) {
					//Telt het percentage van het betreffende vak van de huidige
					//student op met de oude waarde van de som van percentages
					int nieuwPercentage = gemiddeldeVakkenMap.get(vakkenLijst.get(j)) + vakkenMap.get(vakkenLijst.get(j));
					gemiddeldeVakkenMap.remove(vakkenLijst.get(j));
					gemiddeldeVakkenMap.put(vakkenLijst.get(j), nieuwPercentage);
					
					//Hoogt het aantal percentages van het betreffende vak met 1 op
					int nieuwAantal = aantalGemiddeldes.get(vakkenLijst.get(j)) + 1;
					aantalGemiddeldes.remove(vakkenLijst.get(j));
					aantalGemiddeldes.put(vakkenLijst.get(j), nieuwAantal);
					}
				j++;
			}
			i++;
		}
		
		int l = 0;
		
		//De som van percentages, die nu opgeslagen zijn in gemiddeldeVakkenMap
		//per vak worden nu gedeeld door het aantal percentages per vak. Zo wordt
		// het gemiddeld percentage van elk vak berekend
		while(l<vakkenLijst.size()) {
			if(aantalGemiddeldes.get(vakkenLijst.get(l)) != 0) {
				int gemiddeldPercentage = gemiddeldeVakkenMap.get(vakkenLijst.get(l))/aantalGemiddeldes.get(vakkenLijst.get(l));
				gemiddeldeVakkenMap.remove(vakkenLijst.get(l));
				gemiddeldeVakkenMap.put(vakkenLijst.get(l), gemiddeldPercentage);
			}
			l++;
		}
		
		return gemiddeldeVakkenMap;
	}
	
	/**
	 * Berekent de gemiddelde gespendeerde studietijd van alle studenten tesamen
	 * @return gemiddelde gespendeerde studietijd in minuten
	 */
	public int berekenGemiddeldeStudietijdAlleStudenten() {
		int gemiddelde = berekenTotaleStudietijdAlleStudenten() / StudentManager.getInstance().getStudents().size();
		return gemiddelde;
	}
	
	
	/**
	 * Methode die het aantal gestudeerde pagina's per vak teruggeeft
	 * @param student	De student van wie het aantal pagina's wordt berekend per vak
	 * @return HashMap met de vakken en het overeenkomstige aantal pagina's
	 */
	public HashMap<Vak,Integer> berekenAantalPaginasVakken(Student student) {
		HashMap<Vak,Integer> vakkenMap = new HashMap<Vak,Integer>();
		
		String type = "pagina";
		vakkenMap = berekenAantal(student, type);
		
		return vakkenMap;
	}
	
	/**
	 * Methode die het gemiddeld aantal paginas per vak voor alle studenten berekent
	 * @return HashMap met de vakken en het overeenkomstige aantal pagina's
	 */
	public HashMap<Vak,Integer> berekenGemiddeldAantalPaginas() {
		
		HashMap<Vak,Integer> gemiddeldePaginasMap = new HashMap<Vak,Integer>();
		
		List<Vak> vakkenLijst = new ArrayList<Vak>();
		vakkenLijst = VakManager.getInstance().getVakken();
		
		HashMap<Vak,Integer> aantalGemiddeldes = new HashMap<Vak,Integer>();
		
		List<Student> studenten = StudentManager.getInstance().getStudents();
		
		int k=0;
		while(k<vakkenLijst.size()) {
			gemiddeldePaginasMap.put(vakkenLijst.get(k), 0);
			aantalGemiddeldes.put(vakkenLijst.get(k), 0);
			k++;
		}
		
		int i = 0;
		while(i<studenten.size()) {
			HashMap<Vak,Integer> vakkenMap = new HashMap<Vak,Integer>();
			vakkenMap = berekenPercentagesVakken(studenten.get(i));
			int j = 0;
			while(j<vakkenLijst.size()) {
				if(vakkenMap.get(vakkenLijst.get(j)) != null) {
					
					int nieuwAantalPaginas = gemiddeldePaginasMap.get(vakkenLijst.get(j)) + vakkenMap.get(vakkenLijst.get(j));
					gemiddeldePaginasMap.remove(vakkenLijst.get(j));
					gemiddeldePaginasMap.put(vakkenLijst.get(j), nieuwAantalPaginas);
					
					
					int nieuwAantal = aantalGemiddeldes.get(vakkenLijst.get(j)) + 1;
					aantalGemiddeldes.remove(vakkenLijst.get(j));
					aantalGemiddeldes.put(vakkenLijst.get(j), nieuwAantal);
					}
				j++;
			}
			i++;
		}
		int l = 0;
		while(l<vakkenLijst.size()) {
			if(aantalGemiddeldes.get(l) != 0) {
				int gemiddelde = gemiddeldePaginasMap.get(vakkenLijst.get(l))/aantalGemiddeldes.get(vakkenLijst.get(l));
				gemiddeldePaginasMap.remove(vakkenLijst.get(l));
				gemiddeldePaginasMap.put(vakkenLijst.get(l), gemiddelde);
			}
			l++;
		}
		
		return gemiddeldePaginasMap;
	}
	
	/**
	 * Methode die de gemiddelde rating per plaats berekent
	 * @return HashMap met de plaatsen en de overeenkomstige gemiddelde ratings
	 */
	public HashMap<String,Integer> berekenGemiddeldRatingPlaats() {
		HashMap<String,Integer> plaatsMap = new HashMap<String,Integer>();
		
		List<Student> studenten = StudentManager.getInstance().getStudents();
		
		List<String> plaatsenLijst = studiePlaatsLijst;
		
		//Map die het aantal ratings per plaats bevat
		HashMap<String,Integer> ratingAantal = new HashMap<String,Integer>(); 
		
		//Initialisatie van plaatsMap
		int k = 0;
		while(k<plaatsenLijst.size()) {
			plaatsMap.put(plaatsenLijst.get(k), 0);
			ratingAantal.put(plaatsenLijst.get(k), 0);
			k++;
		}
		
		int i = 0;
		while(i<studenten.size()) {
			Student student = studenten.get(i);
			int j = 0;
			while(j<student.getStudies().size()) {
				
				Studie huidigeStudie = student.getStudies().get(j);
				
				Long huidigeRating = huidigeStudie.getRating();
				
				int ratingWaarde = plaatsMap.get(huidigeStudie.getPlaats());
				int nieuweRating =  ratingWaarde + huidigeRating.intValue();
				plaatsMap.remove(huidigeStudie.getPlaats());
				plaatsMap.put(huidigeStudie.getPlaats(), nieuweRating);
				
				int nieuwAantal = ratingAantal.get(huidigeStudie.getPlaats()) + 1;
				ratingAantal.remove(huidigeStudie.getPlaats());
				ratingAantal.put(huidigeStudie.getPlaats(), nieuwAantal);
				
				j++;
			}
		i++;	
		}
		
		int l=0;
		while(l<plaatsenLijst.size()) {
			if(ratingAantal.get(plaatsenLijst.get(l)) != 0) {
				int gemiddeldeRating = plaatsMap.get(plaatsenLijst.get(l)) / ratingAantal.get(plaatsenLijst.get(l));
				plaatsMap.remove(plaatsenLijst.get(l));
				plaatsMap.put(plaatsenLijst.get(l), gemiddeldeRating);
			}
			l++;
		}
		
		return plaatsMap;
	}
	
	
	/**
	 * Berekend voor een student het overeenkomstige aantal van hetType per vak
	 * @param student	De student van wie het aantal moet berekend worden
	 * @param hetType	"pagina" of "studietijd", naargelang welk van de twee men wil berekenen
	 * @return HashMap met vakken als keys en de overeenkomstige waarden van hetType
	 */
	public HashMap<Vak,Integer> berekenAantal(Student student, String hetType) {
		
		String type = hetType;
		
		HashMap<Vak,Integer> vakkenMap = new HashMap<Vak,Integer>();
		List<Studie> studies = student.getStudies();
		List<Vak> vakkenLijst = new ArrayList<Vak>();
		vakkenLijst = student.getVakken();
		
		int k=0;
		while(k<vakkenLijst.size()) {
			vakkenMap.put(vakkenLijst.get(k), 0);
			k++;
		}
		
		int i=0;
		while(i < studies.size()) {
			int j = 0;
			while(j < vakkenLijst.size()) {
				if(vakkenLijst.get(j) == studies.get(i).getVak()) {
					if(type.equals("pagina")) {
						Long aantalPaginas = studies.get(i).getAantalPag();
						int totaalAantalPaginas = vakkenMap.get(vakkenLijst.get(j)) + aantalPaginas.intValue();
						vakkenMap.remove(vakkenLijst.get(j));
						vakkenMap.put(vakkenLijst.get(j), totaalAantalPaginas);
					}
					
					if(type.equals("studietijd")) {
						Long duur = studies.get(i).getDuur();
						int totaleDuur = vakkenMap.get(vakkenLijst.get(j)) + duur.intValue();
						vakkenMap.remove(vakkenLijst.get(j));
						vakkenMap.put(vakkenLijst.get(j), totaleDuur);
					}
				}
				j++;
			}
			i++;
		}
		return vakkenMap;
	}
	
	
	/**
	 * Voeg de mogelijke studieplaatsen toe aan (initialisatie)
	 */
	private void addStudiePlaatsen() {
		//Men moet er echter rekening mee houden dat dezelfde strings in 
		//main.jsp zijn hardgedecodeerd indien men wijzigingen aanbrengt
		studiePlaatsLijst= new ArrayList<String>();
		studiePlaatsLijst.add("kot");
		studiePlaatsLijst.add("campus");
		studiePlaatsLijst.add("bib");
		studiePlaatsLijst.add("thuis");
		studiePlaatsLijst.add("jet");
		studiePlaatsLijst.add("andere");
	}
	
}
